<?php
require_once dirname(__FILE__) . '/libraries/ServiceBase.php';
/**
 * 计费接口调用封装
 * @author Zhang zhan <zhangzhan@snda.com>
 */


class OpBillingException extends Exception {

}

/**
 * 参数错误异常
 */
class OpBillingParamException extends OpBillingException {

}

/**
 * 对计费接口的封装。
 * 接口参数使用数组提交,
 * 人如果缺少参数将抛出异常。
 *
 */
class OpBilling {

    //TODO 将各个状态补全方便显示
    //结算状态从状态号到文字的说明:
    static public $STATE_STR_MAP = array('1'=>'已确认',
                                         '0'=>'待确认'
                                         );

    static public $BILLING_STATE_STR_MAP = array('1'=>'已结算',
                                         '0'=>'待结算'
                                         );

    //重要错误号定义,均定义为字符串形式 0为无错误
    const ERR_OPENCHANNELAPP_EXIST = '-10249024';
    const ERR_OPENAPP_EXIST = '-10249004';

    private $_interface_host = null;
    private $_cur_time;
    private $_cur_time_s;

    private $_end_time_s = '2099-12-31 23:59:59';
    private function __construct() {
        $this->_cur_time = time();
        $this->_cur_time_s = date('Y-m-d H:i:s', $this->_cur_time);
//        $this->_interface_host = Oa_Util_Config::getConfig('billing_interface_host');
        $this->_interface_host = sdk_fetch_config(SDK_ENV . 'billing_interface_host');
    }




    /**
     * 根据param 构建 html请求参数
     * 发出具体的请求,$get_url 为具体要请求的地址
     * 以http开头将使用$get_url为完整地址,
     * 以'/'开头或者非http开头，使用$this->_interface_url作为host
     */
    private function request($get_url, $param) {
        if (substr($get_url, 0, 4) != 'http') {
            if ($get_url[0] != '/') {
                $get_url = '/' . $get_url;
            }
            $get_url = $this->_interface_host . $get_url;
        }

        $param_s = http_build_query($param);
        if (empty($param_s)) {
            throw new OpBillingException('build query string error');
        }

        $get_url .= '?' . $param_s;

        $result = @file_get_contents($get_url);
        //暂时去掉接口调用
        //$result = '{"Result":"0"}';
        if ($result === false) {
            throw new OpBillingException('request interface Error。url:' . $get_url);
        }

        return $result;
    }

    /**
     * 对接口返回的数据进行解析，方便php处理
     */
    private function parseResult($result) {
        $result_decode = json_decode($result, true);
        if (empty($result_decode)) {
            throw new OpBillingException('result json decode error!');
        }

        return $result_decode;
    }


    /**
     * 检查数据定义,只对数据类型进行基础检查。
     * 只允许 string, 数字类型
     * 非默认参数的传入参数将也会进入接口查询，而不会剔除。
     *
     * @throws OpBillingParamException
     * @return array 返回经过检查的参数（包括默认参数补填）
     */
    private function checkParam($param, $param_def) {
        if (!is_array($param)) {
            throw new OpBillingParamException('param must be Array');
        }

        foreach ($param_def as $key => $val) {
            $param_val = null;
            if (isset($param[$key])) {
                $param_val = $param[$key];
            } else {
                $param_val = $val;
                $param[$key] = $param_val;
            }

            if ($param_val === null) {
                throw new OpBillingParamException('param "' . $key . '" not set');
            }

            if (!is_string($param_val) && !is_numeric($param_val) && !is_int($param_val)) {
                throw new OpBillingParamException('param value must be string or numeric');
            }
        }

        return $param;
    }


    /**
     * 开通应用
     */
    static public function OpenApp($param) {
        //参数描述，描述该方法要处理哪些参数，参数是否有默认值。
        //key为需要参数，value为默认值，如果value为null没有默认值
        static $param_def = array(
            'pt' => null,
            'accountName' => null,
            'appId' => null,
            'appName' => null,
            'startTime' => null,
            'endTime'=> null,
            'divideRole' => null,
            'state' => null,
        );

        $billing_obj = self::GetInstance();
        $param_def['startTime'] = $billing_obj->_cur_time_s;
        $param_def['endTime'] = $billing_obj->_end_time_s;

        $param = $billing_obj->checkParam($param, $param_def);
        $get_url = 'OpenApp.do';
        $result = $billing_obj->parseResult($billing_obj->request($get_url, $param));
        return $result;
    }

    /**
     *
     */
    static public function UpdateApp($param) {
        static $param_def = array(
            'pt' => null,
            'accountName' => null,
            'appId' => null,
            'startTime' => null,
            'endTime'=> null,
            'divideRole' => null,
            'state' => null,
        );

        $billing_obj = self::GetInstance($param);
        $param_def['startTime'] = $billing_obj->_cur_time_s;
        $param_def['endTime'] = $billing_obj->_end_time_s;

        $param = $billing_obj->checkParam($param, $param_def);
        $get_url = 'UpdateApp.do';
        $result = $billing_obj->parseResult($billing_obj->request($get_url, $param));
        return $result;
    }

    /**
     * 开通或者修改渠道应用
     * 默认调用开通渠道应用，如果返回该渠道应用已经存在的情况下
     * 再调用修改渠道接口
     */
    static public function OpenUpdateChannelApp($param) {
        $result = self::OpenChannelApp($param);
        if ($result['Result'] == self::ERR_OPENCHANNELAPP_EXIST) {
            $result = self::UpdateChannelApp($param);
        }

        return $result;
    }
    /**
     *
     */
    static public function OpenChannelApp($param) {
        static $param_def = array(
            'pt' => null,
            'accountName' => null,
            'channelNo' => null,
            'channelName' => null,
            'appId' => null,
            'startTime' => null,
            'endTime'=> null,
            'divideRole' => null,
            'state' => null,
        );

        $billing_obj = self::GetInstance();
        $param_def['startTime'] = $billing_obj->_cur_time_s;
        $param_def['endTime'] = $billing_obj->_end_time_s;

        $param = $billing_obj->checkParam($param, $param_def);
        $get_url = 'OpenChannelApp.do';
        $result = $billing_obj->parseResult($billing_obj->request($get_url, $param));
        return $result;
    }

    /**
     *
     */
    static public function UpdateChannelApp($param) {
        static $param_def = array(
            'pt' => null,
            'channelNo' => null,
            'appId' => null,
            'startTime' => null,
            'endTime'=> null,
            'divideRole' => null,
            'state' => null,
        );

        $billing_obj = self::GetInstance();
        $param_def['startTime'] = $billing_obj->_cur_time_s;
        $param_def['endTime'] = $billing_obj->_end_time_s;

        $param = $billing_obj->checkParam($param, $param_def);
        $get_url = 'UpdateChannelApp.do';
        $result = $billing_obj->parseResult($billing_obj->request($get_url, $param));
        return $result;
    }

    /**
     *
     */
    static public function OpenMultiChannelsApp($param) {
        static $param_def = array(
            'channelNos' => null,
            'appId' => null,
            'startTime' => null,
            'endTime'=> null,
            'divideRole' => null,
            'state' => null,
        );

        $billing_obj = self::GetInstance();
        $param_def['startTime'] = $billing_obj->_cur_time_s;
        $param_def['endTime'] = $billing_obj->_end_time_s;

        $param = $billing_obj->checkParam($param, $param_def);
        $get_url = 'OpenChannelsApp.do';
        $result = $billing_obj->parseResult($billing_obj->request($get_url, $param));
        return $result;
    }

    /**
     *
     */
    static public function QueryChannelDaily($param) {
        static $param_def = array(
            'startTime' => null,
            'endTime'=> null,
        );

        $billing_obj = self::GetInstance();
        $param_def['startTime'] = $billing_obj->_cur_time_s;
        $param_def['endTime'] = $billing_obj->_end_time_s;

        $param = $billing_obj->checkParam($param, $param_def);
        $get_url = 'QueryChannelDaily.do';
        $result = $billing_obj->parseResult($billing_obj->request($get_url, $param));
        return $result;
    }

    /**
     *
     */
    static public function QueryChannelMonthly($param) {
        static $param_def = array(
            'startTime' => null,
            'endTime'=> null,
        );

        $billing_obj = self::GetInstance();
        $param_def['startTime'] = $billing_obj->_cur_time_s;
        $param_def['endTime'] = $billing_obj->_end_time_s;

        $param = $billing_obj->checkParam($param, $param_def);
        $get_url = 'QueryChannelMonth.do';
        $result = $billing_obj->parseResult($billing_obj->request($get_url, $param));
        return $result;
    }

    /**
     * @return OpBilling
     */
    static public function GetInstance() {
        static $_obj = null;
        if (!is_object($_obj)) {
            $_obj = new OpBilling();
        }
        return $_obj;
    }
}
